// Copyright 2017 Baidu Inc. All Rights Reserved.
// Author: Su Hao (suhao@baidu.com)
//
// Description: The wrapper for user's transport.

#include "baidu_ca_trans_wrapper.h"
#include "baidu_ca_internal.h"

typedef struct _baidu_ca_transport_t {
    bca_soc_create_f        f_create;
    bca_soc_connect_f       f_connect;
    bca_soc_recv_f          f_recv;
    bca_soc_recv_timeout_f  f_recv_timeout;
    bca_soc_send_f          f_send;
    bca_soc_close_f         f_close;
    bca_soc_destroy_f       f_destroy;
} bca_transport_t;

BCA_LOC_IMPL bca_transport_t s_bca_transport = {NULL};

BCA_EXT_IMPL void baidu_ca_transport_init(bca_soc_create_f f_create,
                                          bca_soc_connect_f f_conn,
                                          bca_soc_send_f f_send,
                                          bca_soc_recv_f f_recv,
                                          bca_soc_recv_timeout_f f_recv_timeout,
                                          bca_soc_close_f f_close,
                                          bca_soc_destroy_f f_destroy) {
    s_bca_transport.f_create = f_create;
    s_bca_transport.f_connect = f_conn;
    s_bca_transport.f_send = f_send;
    s_bca_transport.f_recv = f_recv;
    s_bca_transport.f_recv_timeout = f_recv_timeout;
    s_bca_transport.f_close = f_close;
    s_bca_transport.f_destroy = f_destroy;
}

BCA_INT_IMPL bca_status_t bca_trans_wrapper_create(bca_trans_ptr trans) {
    if (trans && s_bca_transport.f_create) {
        trans->ctx = s_bca_transport.f_create(trans->soc_context);
    }

    return trans && trans->ctx ? BCA_NO_ERR : BCA_ERR_INTERNAL;
}

BCA_INT_IMPL bca_status_t bca_trans_wrapper_connect(bca_trans_ptr trans,
        const bca_addr_t* addr) {
    bca_status_t rs = BCA_ERR_INTERNAL;

    if (trans && s_bca_transport.f_connect) {
        rs = s_bca_transport.f_connect(trans->ctx, addr);
    }

    return rs;
}

BCA_INT_IMPL bca_status_t bca_trans_wrapper_send(bca_trans_ptr trans,
                                                 const void* data,
                                                 bca_size_t size,
                                                 const bca_addr_t* addr) {
    bca_status_t rs = BCA_ERR_INTERNAL;

    if (trans && s_bca_transport.f_send) {
        rs = s_bca_transport.f_send(trans->ctx, data, size, addr);
    }

    return rs;
}

BCA_INT_IMPL bca_status_t bca_trans_wrapper_recv(bca_trans_ptr trans,
                                                 void* data,
                                                 bca_size_t size,
                                                 bca_addr_t* addr) {
    bca_status_t rs = BCA_ERR_INTERNAL;

    if (trans) {
        if (s_bca_transport.f_recv_timeout) {
            rs = s_bca_transport.f_recv_timeout(trans->ctx, data, size, trans->read_timeout, addr);
        } else if (s_bca_transport.f_recv) {
            rs = s_bca_transport.f_recv(trans->ctx, data, size, addr);
        } else {
          // Do nothing
        }
    }

    return rs;
}

BCA_INT_IMPL bca_status_t bca_trans_wrapper_recv_timeout(bca_trans_ptr trans,
                                                         void* data,
                                                         bca_size_t size,
                                                         bca_u32_t timeout,
                                                         bca_addr_t* addr) {
    bca_status_t rs = BCA_ERR_INTERNAL;

    if (trans) {
        if (s_bca_transport.f_recv_timeout) {
            rs = s_bca_transport.f_recv_timeout(trans->ctx, data, size, timeout, addr);
        }
    }

    return rs;
}

BCA_INT_IMPL bca_status_t bca_trans_wrapper_close(bca_trans_ptr trans) {
    bca_status_t rs = BCA_ERR_INTERNAL;

    if (trans && s_bca_transport.f_close) {
        rs = s_bca_transport.f_close(trans->ctx);
    }

    return rs;
}

BCA_INT_IMPL bca_status_t bca_trans_wrapper_destroy(bca_trans_ptr trans) {
    bca_status_t rs = BCA_ERR_INTERNAL;

    if (trans && s_bca_transport.f_destroy) {
        rs = s_bca_transport.f_destroy(trans->ctx);
    }

    return rs;
}
